﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Xml;
using AppConfigDataProxy;


namespace WebServiceTest
{

    /// <summary>
    /// Summary description for Service1
    /// </summary>
    [WebService(Namespace = "http://lab.epam.com/ns/2008/06/appconfig/",//"http://localhost/AppConfigService/",
                Description = "The Config Service is designed to provide configuration information, previously stored in configuration server")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]    
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class Service : System.Web.Services.WebService, IAppConfigService
    {

        private readonly AppConfigDataProxy.IAppConfigDataProxy _dataProxy;

        public Service()
        {
            _dataProxy = new AppConfigDataProxy.AppConfigDBProxy(null);
            
        }

        public IAppConfigDataProxy DataProxy
        {
            get { return _dataProxy; }
        }

        [WebMethod]
        public string HelloWorld()
        {
            return "Hello, World!";
        }

        /// <summary>
        /// Get config information for given application in xml
        /// </summary>
        /// <param name="appid">Application id</param>
        /// <param name="getschema">Is need be return schema</param>
        /// <param name="App">Return config information for given application in xml</param>
        /// <returns>Schema of config information</returns>
        public System.Xml.XmlNode GetAppConfig(string appid, bool getschema, out App app)
        {
            app = new App();
            app.appid = appid;
            app.Any.AppendChild(DataProxy.GetAppConfig(appid).Config);
            
            XmlNode result = null;

            if (getschema)
                result = DataProxy.GetSchema();

            return result;
        }

        /// <summary>
        /// Get complete config information for all applications.
        /// </summary>
        /// <param name="getschema">Is need be return schema</param>
        /// <param name="Config">Return config information for all applications in xml</param>
        /// <returns>Schema of config information</returns>
        public System.Xml.XmlNode GetConfig(bool getschema, out App[] Config)
        {
            AppInfo[] appConfigs = DataProxy.GetConfig();
            Config = new App[appConfigs.Count()];
            for (int i = 0; i < appConfigs.Count(); i++)
            {
                Config[i] = new App();
                Config[i].appid = appConfigs[i].AppId;
                Config[i].Any = appConfigs[i].Config;
            }
            XmlNode result = null;

            if (getschema)
                result = DataProxy.GetSchema();

            return result;
        }

        /// <summary>
        /// Set Application Configuration for a specific Application
        /// </summary>
        /// <param name="setAppConfigReq">Containe Application id and xml config</param>
        /// <returns>Containe updated application config version</returns>
        public CommonAppVersionResp SetAppConfig( SetAppConfigReq setAppConfigReq)
        {
            App app = setAppConfigReq.App;
            string appId;

            int appVersion;
            appVersion = SetAppConfig(app,out appId);

            CommonAppVersionResp result = new CommonAppVersionResp();
            result.appid = appId;
            result.Version = appVersion;
            return result;
        }

        /// <summary>
        /// Set Application Configuration for a specific Application
        /// </summary>
        /// <param name="App">Application xml config </param>
        /// <param name="appid">Application id</param>
        /// <returns>Updated application config version</returns>
        public int SetAppConfig(App App, out string appid)
        {
            string appId = App.appid;
            appid = appId;
            XmlElement config = App.Any;
            AppInfo appInfo = new AppInfo(appId, config);
            int appVersion;
            appVersion = DataProxy.SetAppConfig(appInfo);
            return appVersion;
        }

        /// <summary>
        /// Set configuration information for all applications
        /// </summary>
        /// <param name="setConfigReq">Containe config information for all application and new schema</param>
        /// <returns>Containe updated config version</returns>
        public CommonVersionResp SetConfig(SetConfigReq setConfigReq)
        {            
            App[] config = setConfigReq.Config;
            XmlElement schema = setConfigReq.Schema;


            int configVersion;

            configVersion = SetConfig(schema, config);

            CommonVersionResp result = new CommonVersionResp();
            result.Version = configVersion;

            return result;
        }

        /// <summary>
        /// Set configuration information for all applications
        /// </summary>
        /// <param name="Schema">Schema of config information</param>
        /// <param name="Config">Config information for all applications</param>
        /// <returns>updated config version</returns>
        public int SetConfig(System.Xml.XmlElement Schema, App[] Config)
        {
            AppInfo[] appConfigs = Config
                .Select(app => new AppInfo(app.appid, app.Any))
                .ToArray();

            int configVersion;
            configVersion = DataProxy.SetConfig(appConfigs, Schema);

            return configVersion;
        }

        /// <summary>
        /// Creates a new application (if provided appid is not already used)
        /// and either sets it’s config to xml provided
        /// </summary>
        /// <param name="addAppReq">Containe config information for new application</param>
        /// <returns>Containe updated application config version</returns>
        public CommonAppVersionResp AddApp( AddAppReq addAppReq)
        {
            App app = addAppReq.App;
            string appId;

            int appVersion = AddApp(app, out appId);

            CommonAppVersionResp result = new CommonAppVersionResp();

            result.appid = appId;
            result.Version = appVersion;
            return result;             
        }


        /// <summary>
        /// Creates a new application (if provided appid is not already used)
        /// and either sets it’s config to xml provided
        /// </summary>
        /// <param name="App">config information for new application</param>
        /// <param name="appid">application id</param>
        /// <returns>Updated application config version</returns>
        public int AddApp(App App, out string appid)
        {
            string appId = App.appid;
            appid = appId;
            var config = App.Any;
            AppInfo appInfo = new AppInfo(appId, config);

            int appVersion;
            appVersion = DataProxy.AddApp(appInfo);

            return appVersion;
        }

        /// <summary>
        /// Remove a specific application from config
        /// </summary>
        /// <param name="appid">Application id what need to be remove</param>
        public void RemoveApp(string appid)
        {
            DataProxy.RemoveApp( appid );
        }

        /// <summary>
        /// Rolls back application configuration to the version provided in request
        /// or previous version if Version parameter was omitted
        /// </summary>
        /// <param name="rollBackAppReq">Containe Application Id and version to which want to roll back. Optional parameter. Out updated config version</param>
        /// <returns>Containe updated application config version</returns>
        public CommonAppVersionResp RollBackApp(RollBackAppReq rollBackAppReq)
        {
            var appid = rollBackAppReq.appid;
            var version = rollBackAppReq.Version;
            RollBackApp(ref version, ref appid );

            var result = new CommonAppVersionResp();            
            result.appid = appid;
            Debug.Assert(version.HasValue, "RollBackApp didnot return updated app version");
            result.Version = version.Value;
            return result;
        }

        /// <summary>
        /// Rolls back configuration to the version provided in request
        /// or previous version if the version parameter was omitted 
        /// </summary>
        /// <param name="rollBackReq">Containe version to which want to roll back. Optional parameter.</param>
        /// <returns>Containe updated config version</returns>
        public CommonVersionResp RollBack(RollBackReq rollBackReq)
        {
            var version = rollBackReq.Version;
            RollBack(ref version);

            var result = new CommonVersionResp();
            Debug.Assert(version.HasValue, "RollBackApp didnot return updated app version");
            result.Version = version.Value;

            return result;
        }

        /// <summary>
        /// Get current version of the requested application config
        /// </summary>
        /// <param name="getAppVersionReq">Containe application id</param>
        /// <returns>containe current version of application config</returns>
        public CommonAppVersionResp GetAppVersion(AppHeader getAppVersionReq)
        {
            var appid = getAppVersionReq.appid;            
            var version = GetAppVersion(ref appid);
            Debug.Assert((appid == getAppVersionReq.appid), "GetAppVersion return version of another (not requested) app");

            var result = new CommonAppVersionResp();
            result.appid = appid;
            result.Version = version;

            return result;
        }

        /// <summary>
        /// Get current config version
        /// </summary>
        /// <param name="getVersionReq"></param>
        /// <returns>Containe current config version</returns>
        public CommonVersionResp GetVersion(CommonEmptyReq getVersionReq)
        {
            var result = new CommonVersionResp();
            result.Version = GetVersion();
            return result;
        }

        /// <summary>
        /// Rolls back application configuration to the version provided in request
        /// or previous version if Version parameter was omitted
        /// </summary>
        /// <param name="Version">Version to which want to roll back. Optional parameter. Out updated config version</param>
        /// <param name="appid">Id of application what have rolled back and updated app version</param>
        public void RollBackApp(ref int? Version, ref string appid)
        {
            if (Version.HasValue)
            {
                int updatedAppVersion = DataProxy.RollBackApp(appid, Version.Value);
                Version = updatedAppVersion;
            }
            else
            {
                int updatedAppVersion = DataProxy.RollBackApp(appid);
                Version = updatedAppVersion;
            }
                        
        }

        /// <summary>
        /// Rolls back configuration to the version provided in request
        /// or previous version if the version parameter was omitted
        /// </summary>
        /// <param name="Version">Version to which want to roll back. Optional parameter. Out updated config version</param>
        public void RollBack(ref int? Version)
        {
            if (Version.HasValue)
            {
                int updatedVersion = DataProxy.RollBack( Version.Value);
                Version = updatedVersion;
            }
            else
            {
                int updatedVersion = DataProxy.RollBack();
                Version = updatedVersion;
            }
        }

        /// <summary>
        /// Get current version of application config
        /// </summary>
        /// <param name="appid">Application id</param>
        /// <returns>Current version of application config</returns>
        public int GetAppVersion(ref string appid)
        {
            int appVersion = DataProxy.GetAppVersion(appid);
            return appVersion;
        }

        /// <summary>
        /// Get current config version
        /// </summary>
        /// <returns>current config version</returns>
        public int GetVersion()
        {
            int configVersion;
            configVersion = DataProxy.GetVersion();
            return configVersion;
        }

        /// <summary>
        /// Get the list of all applications
        /// </summary>
        /// <returns>Array of all applicatuons header</returns>
        public AppHeader[] GetAppList()
        {
            string[] appNameList = DataProxy.GetAppList();
            int countApp = appNameList.Length;
            AppHeader[] appHeaders = new AppHeader[ countApp ];
            for (int i = 0; i < countApp; i++)
            {
                var appHeader = new AppHeader();
                appHeader.appid = appNameList[i];
                appHeaders[i] = appHeader;
            }

            return appHeaders;
        }
    }
}